iT邦幫忙

0

用抽象資料型別簡化 ERP 資料庫維護

  • 分享至 

  • xImage
  •  

跨資料庫支援 × 自動升級 × 一致性設計

field-dbtype-design

1️⃣ 緣起

在 ERP 系統中,資料表結構常隨著需求變動而頻繁調整,且往往需要同時支援 SQL Server/MySQL/PostgreSQL/Oracle 等多種資料庫。

若直接在程式中使用各資料庫的原生型別(如 NVARCHARNUMBER 等),一旦要異動欄位型別或調整長度,就必須修改所有 SQL 定義與程式碼,維護與遷移成本極高。

BeeNET 採用抽象資料型別(Abstract Data Type)的概念,以抽象的 FieldDbType 列舉來定義資料欄位,再由 DbTable 作為資料表結構定義物件。

部署時交由比對工具與命令產生器轉換為各資料庫對應的 DDL / DML 語法,達成跨資料庫支援與自動升級。


2️⃣ 抽象資料型別的優點

  • 防止選錯型別:只需宣告 StringTextDateTime 等直觀型別,由框架自動轉換。
  • 降低全域修改風險:例如改為全面支援 Unicode,只需更新型別對應表。
  • 支援多資料庫:SQL Server、MySQL、PostgreSQL、Oracle 等異質環境一套定義即可。
  • 簡化設計:開發人員不用關心 varchar/nvarchar 等差異。
  • 提升效率:有利於測試、驗證與程式碼產生。

3️⃣ FieldDbType 列舉(抽象層)

抽象資料型別以列舉表示,統一由 DbTable 欄位的 DbType 屬性參照:

/// <summary>
/// 欄位的抽象資料型別(跨資料庫對應)。
/// </summary>
public enum FieldDbType
{
    String,        // 一般字串(具長度)
    Text,          // 大量文字
    Boolean,       // 布林值
    AutoIncrement, // 自動遞增整數(資料表主鍵常用)
    Short,         // 16-bit 整數
    Integer,       // 32-bit 整數
    Long,          // 64-bit 整數
    Decimal,       // 十進位數值(高精度)
    Currency,      // 金額(預設 19,4)
    Date,          // 日期
    DateTime,      // 日期時間
    Guid,          // 全域唯一識別碼
    Binary         // 二進位資料
}

4️⃣ FieldDbType 資料型別對應表

FieldDbType SQL Server MySQL PostgreSQL Oracle
String NVARCHAR(n) VARCHAR(n) VARCHAR(n) VARCHAR2(n)
Text NVARCHAR(MAX) TEXT TEXT CLOB
Boolean BIT TINYINT(1) / BOOLEAN BOOLEAN NUMBER(1)
AutoIncrement INT IDENTITY(1,1) INT AUTO_INCREMENT SERIAL / INT GENERATED ALWAYS AS IDENTITY NUMBER + SEQUENCE
Short SMALLINT SMALLINT SMALLINT NUMBER(5)
Integer INT INT INTEGER NUMBER(10)
Long BIGINT BIGINT BIGINT NUMBER(19)
Decimal DECIMAL(p,s) DECIMAL(p,s) NUMERIC(p,s) NUMBER(p,s)
Currency DECIMAL(19,4) DECIMAL(19,4) NUMERIC(19,4) NUMBER(19,4)
Date DATE DATE DATE DATE
DateTime DATETIME DATETIME TIMESTAMP TIMESTAMP
Guid UNIQUEIDENTIFIER CHAR(36) / BINARY(16) UUID RAW(16)
Binary VARBINARY(MAX) BLOB BYTEA BLOB

5️⃣ BeeNET 元件協作流程

  • DbTable:為資料表結構的定義來源;以 FieldDbType 宣告欄位結構與限制(長度、精度、是否必填)。
  • TableSchemaComparer:比對 DbTable 與實際資料庫結構,找出需新增/修改的欄位與索引。
  • TableSchemaBuilder:依目標資料庫 Provider 產出 DDL/DML(Create/Alter/Index/Default/Sequence 等)並執行升級。

範例:使用 TableSchemaBuilder 建立或更新資料表


// 載入指定 tableName 的 DbTable 定義,執行資料結構比對與更新
var builder = new TableSchemaBuilder(databaseId); 
builder.Execute(dbName, tableName); 

此機制可於部署階段自動比對結構並同步升級。


6️⃣ DbTable 定義範例

DbTable 物件會序列化為 XML 格式,存放於專案中以供版本控制與部署使用。每個資料表的結構定義皆以 XML 檔({TableName}.DbTable.xml)保存,確保開發、測試與正式環境的結構自動保持一致。

st_user 資料表為例,示範 DbTable 定義方式:

<?xml version="1.0" encoding="utf-8"?>
<DbTable DbName="common" TableName="st_user" DisplayName="用戶">
  <Fields>
    <DbField FieldName="sys_no" Caption="流水號" DbType="AutoIncrement" />
    <DbField FieldName="sys_rowid" Caption="唯一識別" DbType="Guid" />
    <DbField FieldName="sys_id" Caption="用戶帳號" DbType="String" Length="20" />
    <DbField FieldName="sys_name" Caption="用戶名稱" DbType="String" Length="20" />
    <DbField FieldName="password" Caption="登入密碼" DbType="String" Length="40" />
    <DbField FieldName="email" Caption="電子郵件" DbType="String" Length="100" />
    <DbField FieldName="note" Caption="備註" DbType="String" Length="200" />
    <DbField FieldName="sys_insert_time" DisplayName="寫入時間" DbType="DateTime" />
  </Fields>
  <Indexes>
    <DbTableIndex Name="pk_{0}" Unique="true" PrimaryKey="true">
      <IndexFields>
        <IndexField FieldName="sys_no" />
      </IndexFields>
    </DbTableIndex>
    <DbTableIndex Name="rx_{0}" Unique="true">
      <IndexFields>
        <IndexField FieldName="sys_rowid" />
      </IndexFields>
    </DbTableIndex>
    <DbTableIndex Name="ux_{0}" Unique="true">
      <IndexFields>
        <IndexField FieldName="sys_id" />
      </IndexFields>
    </DbTableIndex>
  </Indexes>
</DbTable>

7️⃣ 實務價值

  1. 快速因應需求變更:新增欄位或調整型別,只需修改定義檔。
  2. 多資料庫佈署彈性:支援 SQL Server/MySQL/PostgreSQL/Oracle。
  3. 一致性與可讀性:定義檔與資料表結構保持一致,可由框架自動生成對應的物件模型。
  4. 長期維護優勢:降低手動修改風險,符合模組化與低耦合設計。

✅ 結語

抽象資料型別讓資料結構設計更具一致性與延展性,
DbTable、TableSchemaComparer 與 TableSchemaBuilder 共同構成了 BeeNET 在資料結構層的自動化核心。

透過這樣的架構,ERP 系統能在多資料庫與持續演進的需求下,
仍保持結構一致、部署順暢,並有效降低長期維護成本。

FieldDbType 的設計使開發人員能專注於商業邏輯與流程創新,
而不必被資料庫型別與結構差異所綁架,真正實現高效與穩定並行的開發模式。


📘 HackMD 原文筆記:
👉 https://hackmd.io/@jeff377/field-dbtype-design

📢 歡迎轉載,請註明出處
📬 歡迎追蹤我的技術筆記與實戰經驗分享
FacebookHackMDGitHubNuGet


圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言